package com.xpec.cipher.h5handler;

import java.security.KeyPair;
import java.util.Arrays;

import javax.crypto.Cipher;

import com.xpec.cipher.CipherConnectionConstant;
import com.xpec.cipher.CipherConnectionStatus;
import com.xpec.cipher.CipherHandler;
import com.xpec.cipher.algorithm.RC4;
import com.xpec.cipher.handler.CipherConnectionPacketHandler;
import com.xpec.cipher.tals.PseudoRandom;
import com.xpec.cipher.tals.TalsConstance;

public class H5ServerPreMasterHandler implements CipherConnectionPacketHandler
{

	@Override
	public void receiveHandle(CipherHandler cipherHandler)
	{
		int contentType = cipherHandler.readUnsignedByteFromRealContent();
		if (contentType == TalsConstance.CONTENT_TYPE_HAND_SHAKE)
		{
			int handShakeType = cipherHandler.readUnsignedByteFromRealContent();
			if (handShakeType == TalsConstance.HAND_SHAKE_TYPE_CLIENT_PRE_MASTER)
			{
				int remainSize = cipherHandler.getRealContentRemain();
				byte[] encryptedPre = new byte[remainSize];

				cipherHandler.readByteFromRealContent(encryptedPre);
				// /////////////////////
				byte[] tmp = new byte[encryptedPre.length - 4];
				System.arraycopy(encryptedPre, 4, tmp, 0, encryptedPre.length - 4);
				encryptedPre = tmp;
				// //////////////////////
				Cipher cipher = null;
				try
				{
					cipher = Cipher.getInstance("RSA/ECB/NOPadding");

					KeyPair keyPair = (KeyPair) cipherHandler
							.getParameter(CipherConnectionConstant.PARA_KEY_KEY_PAIR);
					cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
					tmp = cipher.doFinal(encryptedPre);
				}
				catch (Exception e)
				{
					e.printStackTrace();
					throw new RuntimeException(e);
				}
				// /////////////////////
				byte[] PreMaster = new byte[46];
				System.arraycopy(tmp, tmp.length - 46, PreMaster, 0, 46);
				// //////////////////////

				byte[] clientRandom = (byte[]) cipherHandler
						.getParameter(CipherConnectionConstant.PARA_KEY_CLIENT_RANDOM);

				byte[] serverRandom = (byte[]) cipherHandler
						.getParameter(CipherConnectionConstant.PARA_KEY_SERVER_RANDOM);

				byte[] masterKey = PseudoRandom.generatePRG(PreMaster, clientRandom, serverRandom);
				byte[] macKey = Arrays.copyOfRange(masterKey, 0, 16);
				byte[] key = Arrays.copyOfRange(masterKey, 32, 48);

				// 保存masterkey
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_MASTER_KEY, masterKey);
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_MAC_KEY, macKey);

				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_KEY, key);

				int cipherAlgorithm = (Byte) cipherHandler.getParameter(
						CipherConnectionConstant.PARA_KEY_CIPHER_ALGO);
				Object algo = genCipherAlgo(cipherHandler, key, cipherAlgorithm);
				if (null != algo)
					cipherHandler.setParameter(
							CipherConnectionConstant.PARA_KEY_SERVER_CIPHER_OBJECT, 
							algo);

				//System.out.println("pre master finish!");
				
				// 设置状态
				cipherHandler.setParameter(CipherConnectionConstant.PARA_KEY_STATUS,
					CipherConnectionStatus.CHANGE_CIPHER);
			}
		}
	}

	/**
	 * 通过Cihper算法和key生成好以后用于Cipher过程的算法对象。
	 * @author Francois
	 * @param cipherHandler
	 * @param key
	 * @param cipherAlgorithm
	 */
	protected static Object genCipherAlgo(CipherHandler cipherHandler, byte[] key,
			int cipherAlgorithm)
	{
		switch (cipherAlgorithm) {
		case TalsConstance.DATA_ENCRYPT_ALGORITHM_ARC4:
			RC4 algo = new RC4(key);
			return algo;
		}
		return null;
	}

	@Override
	public void sendHandle(CipherHandler cipherHandler)
	{
		cipherHandler.passMessage(CipherHandler.PASS_MESSAGE_SEND);
	}

}